#include "context.h"

Context *context_init(coroutine_func_t fn,size_t stack_size,void *private_data){
	Context *ctx = (Context *)malloc(sizeof(Context));
	if(!ctx){
		printf("malloc error\n");
		exit(-1);
	}

	ctx->fn_ = fn;
	ctx->stack_size_ = stack_size;
	ctx->private_data_ = private_data;
	ctx->ctx_ = ctx->swap_ctx_ = NULL;
	ctx->end_ = false;

	ctx->swap_in = context_swap_in;
	ctx->swap_out = context_swap_out;

	ctx->stack_ = (char *)malloc(stack_size);
	if(!ctx->stack_){
		printf("malloc error\n");
		exit(-1);
	}

	void *sp = (void *)((char *)ctx->stack_ + stack_size);
	ctx->ctx_ = make_fcontext(sp,ctx->stack_size_,(void (*)(intptr_t))&context_func);

	return ctx;
}

void context_dest(Context *ctx){
	free(ctx);
}

int context_swap_out(Context *ctx){
	jump_fcontext(&ctx->ctx_,ctx->swap_ctx_,(intptr_t)ctx,1);
	return 0;
}

int context_swap_in(Context *ctx){
	jump_fcontext(&ctx->swap_ctx_,ctx->ctx_,(intptr_t)ctx,1);
	return 0;
}

void context_func(void *arg){
	Context *ctx = (Context *)arg;
	ctx->fn_(ctx->private_data_);
	ctx->end_ = true;
	ctx->swap_out(ctx);
}

bool context_is_end(Context *ctx){
	return ctx->end_;
}
